package com.minimalist.common.config.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import java.util.HashMap;
import java.util.Map;

/**
 * Sentinel配置类
 *
 * @author minimalist
 */
@Configuration
public class SentinelConfig{

    private static final Logger log = LoggerFactory.getLogger(SentinelConfig.class);

    /**
     * 自定义限流异常处理
     */
    @Bean
    public BlockExceptionHandler blockExceptionHandler(){
        return (HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) -> {
            Map<String, Object> result = new HashMap<>();

            switch (e){
                case FlowException flowException -> {
                    result.put("code", 429);
                    result.put("message", "请求被限流，请稍后再试");
                }
                case DegradeException degradeException -> {
                    result.put("code", 503);
                    result.put("message", "服务降级，请稍后再试");
                }
                case ParamFlowException paramFlowException -> {
                    result.put("code", 429);
                    result.put("message", "热点参数限流，请稍后再试");
                }
                case SystemBlockException systemBlockException -> {
                    result.put("code", 503);
                    result.put("message", "系统负载过高，请稍后再试");
                }
                case AuthorityException authorityException -> {
                    result.put("code", 403);
                    result.put("message", "授权规则不通过，拒绝访问");
                }
                case null, default -> {
                    result.put("code", 500);
                    result.put("message", "未知限流异常，请稍后再试");
                }
            }

            String exName;
            if (e == null){
                exName = "未知限流异常";
            } else{
                exName = e.getClass().getSimpleName();
            }
            log.warn("Sentinel 资源名称：{} 限流异常: {}, 请求路径: {}", resourceName, exName, request.getRequestURI());

            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            new ObjectMapper().writeValue(response.getWriter(), result);
        };
    }
}